﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.SharePoint.Administration;
using Microsoft.Win32;
using Umbrella.Net.Contracts;
using System.IO;

namespace Umbrella.Whs.SharePoint
{
    public sealed class InstallationManager
    {
        public const string PropertyUmbrellaReleaseId = "UmbrellaReleaseId";

        public const int CentralAdministrationPort = 48080;
        public const int UmbrellaWebsitePort = 38080;
        public const int RootLanguageLCID = 1033;
        public const string InstallationConfigAndLogDir = @"D:\folders\{f13fd7c7-cb8f-4959-aa4d-89204d65e3ad}\SharePointSetup";
        public const string InstallationTempDir = @"D:\folders\{f13fd7c7-cb8f-4959-aa4d-89204d65e3ad}\SharePointSetup\InstWizTemp";

        public enum InstallationStatus
        {
            NotInstalled,
            Installed,
            NotUmbrella,
        }

        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(InstallationManager));
        private string _sharePointInstallPath;
        private string _configDatabaseConnectionString;

        public SharePointPlatform CurrentPlatform
        {
            get
            {
                if (Marshal.SizeOf(typeof(IntPtr)) == 8)
                    return SharePointPlatform.X64;

                return SharePointPlatform.X86;
            }
        }

        /// <summary>
        /// path to the SharePoint's "12" directory
        /// </summary>
        public string SharePointInstallPath
        {
            get
            {
                if (_sharePointInstallPath == null)
                {
                    _sharePointInstallPath = Convert.ToString(Registry.GetValue(
                        @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0",
                        "Location",
                        null
                        ));
                }

                return _sharePointInstallPath;
            }
        }

        public string ConfigDatabaseConnectionString
        {
            get
            {
                if (_configDatabaseConnectionString == null)
                {
                    _configDatabaseConnectionString = Convert.ToString(Registry.GetValue(
                        @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0\Secure\ConfigDB",
                        "dsn",
                        null
                        ));
                }

                return _configDatabaseConnectionString;
            }
        }

        public bool IsSSEEInstalled
        {
            get
            {
                try
                {
                    using (var s = Installer.OpenProduct(Whs.Properties.Constants.SqlServerEmbeddedEditionProductCode))
                    {
                        return (s != null);
                    }
                }
                catch (Exception x)
                {
                    _log.Warn("Failed to open SQL Server Embedded Edition from MSI database", x);

                    return false;
                }
            }
        }

        public bool IsSharePointInstalled
        {
            get
            {
                try
                {
                    using (var s = Installer.OpenProduct(Whs.Properties.Constants.SharePointWss30ProductCode))
                    {
                        return (s != null);
                    }
                }
                catch (Exception x)
                {
                    _log.Warn("Failed to open SharePoint from MSI database", x);

                    return false;
                }
            }
        }

        public Version CurrentSharePointVersion
        {
            get
            {
                if (!IsSharePointInstalled)
                    return null;

                var v = Convert.ToString(Registry.GetValue(
                    @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0",
                    "Version",
                    null
                    ));

                if (string.IsNullOrEmpty(v))
                    return null;

                return new Version(v);
            }
        }

        public Uri CentralAdministrationUrl
        {
            get
            {
                if (!IsSharePointInstalled)
                    return null;

                var v = Convert.ToString(Registry.GetValue(
                    @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0\WSS",
                    "CentralAdministrationURL",
                    null
                    ));

                if (string.IsNullOrEmpty(v))
                    return null;

                return new Uri(v);
            }
        }

        public InstallationStatus GetInstallationStatus()
        {
            if (!this.IsSharePointInstalled)
                return InstallationStatus.NotInstalled;

            try
            {
                var farm = SPFarm.Local;

                if (!farm.Properties.ContainsKey(PropertyUmbrellaReleaseId))
                    return InstallationStatus.NotUmbrella;
            }
            catch (Exception x)
            {
                _log.Warn("Failed to determine installation status; falling back to NotUmbrella mode", x);

                return InstallationStatus.NotUmbrella;
            }

            return InstallationStatus.Installed;
        }

        public void SetInstallationReleaseId()
        {
            var farm = SPFarm.Local;

            farm.Properties[PropertyUmbrellaReleaseId] = Whs.UmbrellaVersion.VersionId;

            farm.Update();
        }

        public void Refresh()
        {
            _configDatabaseConnectionString = null;
            _sharePointInstallPath = null;
        }

        public void CleanupInstallationTempDir()
        {
            try
            {
                var d = new DirectoryInfo(InstallationTempDir);

                if (d.Exists)
                    d.Delete(true);
            }
            catch (Exception ex)
            {
                _log.Warn("Failed to clean-up temporary installation directory: " + InstallationTempDir, ex);
            }
        }

        public InstallationManager()
        {
        }
    }
}
